home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_002 / microemacs / random.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  387 lines

  1. /*
  2.  * This file contains the command processing functions for a number of random
  3.  * commands. There is no functional grouping here, for sure.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include        "ed.h"
  8.  
  9. int     tabsize;                        /* Tab size (0: use real tabs)  */
  10.  
  11. /*
  12.  * Set fill column to n. 
  13.  */
  14. setfillcol(f, n)
  15. {
  16.         fillcol = n;
  17.         return(TRUE);
  18. }
  19.  
  20. /*
  21.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  22.  * the character that is under the cursor (in octal), and the fraction of the
  23.  * text that is before the cursor. The displayed column is not the current
  24.  * column, but the column that would be used on an infinite width display.
  25.  * Normally this is bound to "C-X =".
  26.  */
  27. showcpos(f, n)
  28. {
  29.         register LINE   *clp;
  30.         register long   nch;
  31.         register int    cbo;
  32.         register long   nbc;
  33.         register int    cac;
  34.         register int    ratio;
  35.         register int    col;
  36.         register int    i;
  37.         register int    c;
  38.  
  39.         clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  40.         cbo = 0;
  41.         nch = 0;
  42.         for (;;) {
  43.                 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  44.                         nbc = nch;
  45.                         if (cbo == llength(clp))
  46.                                 cac = '\n';
  47.                         else
  48.                                 cac = lgetc(clp, cbo);
  49.                 }
  50.                 if (cbo == llength(clp)) {
  51.                         if (clp == curbp->b_linep)
  52.                                 break;
  53.                         clp = lforw(clp);
  54.                         cbo = 0;
  55.                 } else
  56.                         ++cbo;
  57.                 ++nch;
  58.         }
  59.         col = getccol(FALSE);                   /* Get real column.     */
  60.         ratio = 0;                              /* Ratio before dot.    */
  61.         if (nch != 0)
  62.                 ratio = (100L*nbc) / nch;
  63.         mlwrite("X=%d Y=%d CH=0x%x .=%D (%d%% of %D)",
  64.                 col+1, currow+1, cac, nbc, ratio, nch);
  65.         return (TRUE);
  66. }
  67.  
  68. /*
  69.  * Return current column.  Stop at first non-blank given TRUE argument.
  70.  */
  71. getccol(bflg)
  72. int bflg;
  73. {
  74.         register int c, i, col;
  75.         col = 0;
  76.         for (i=0; i<curwp->w_doto; ++i) {
  77.                 c = lgetc(curwp->w_dotp, i);
  78.                 if (c!=' ' && c!='\t' && bflg)
  79.                         break;
  80.                 if (c == '\t')
  81.                         col |= 0x07;
  82.                 else if (c<0x20 || c==0x7F)
  83.                         ++col;
  84.                 ++col;
  85.         }
  86.         return(col);
  87. }
  88.  
  89. /*
  90.  * Twiddle the two characters on either side of dot. If dot is at the end of
  91.  * the line twiddle the two characters before it. Return with an error if dot
  92.  * is at the beginning of line; it seems to be a bit pointless to make this
  93.  * work. This fixes up a very common typo with a single stroke. Normally bound
  94.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  95.  */
  96. twiddle(f, n)
  97. {
  98.         register LINE   *dotp;
  99.         register int    doto;
  100.         register int    cl;
  101.         register int    cr;
  102.  
  103.         dotp = curwp->w_dotp;
  104.         doto = curwp->w_doto;
  105.         if (doto==llength(dotp) && --doto<0)
  106.                 return (FALSE);
  107.         cr = lgetc(dotp, doto);
  108.         if (--doto < 0)
  109.                 return (FALSE);
  110.         cl = lgetc(dotp, doto);
  111.         lputc(dotp, doto+0, cr);
  112.         lputc(dotp, doto+1, cl);
  113.         lchange(WFEDIT);
  114.         return (TRUE);
  115. }
  116.  
  117. /*
  118.  * Quote the next character, and insert it into the buffer. All the characters
  119.  * are taken literally, with the exception of the newline, which always has
  120.  * its line splitting meaning. The character is always read, even if it is
  121.  * inserted 0 times, for regularity. Bound to "M-Q" (for me) and "C-Q" (for
  122.  * Rich, and only on terminals that don't need XON-XOFF).
  123.  */
  124. quote(f, n)
  125. {
  126.         register int    s;
  127.         register int    c;
  128.  
  129.         c = (*term.t_getchar)();
  130.         if (n < 0)
  131.                 return (FALSE);
  132.         if (n == 0)
  133.                 return (TRUE);
  134.         if (c == '\n') {
  135.                 do {
  136.                         s = lnewline();
  137.                 } while (s==TRUE && --n);
  138.                 return (s);
  139.         }
  140.         return (linsert(n, c));
  141. }
  142.  
  143. /*
  144.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  145.  * tab into file.  If given argument, n, of zero, change to true tabs.
  146.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  147.  * done in this slightly funny way because the tab (in ASCII) has been turned
  148.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  149.  */
  150. tab(f, n)
  151. {
  152.         if (n < 0)
  153.                 return (FALSE);
  154.         if (n == 0 || n > 1) {
  155.                 tabsize = n;
  156.                 return(TRUE);
  157.         }
  158.         if (! tabsize)
  159.                 return(linsert(1, '\t'));
  160.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  161. }
  162.  
  163. /*
  164.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  165.  * and then back up over them. Everything is done by the subcommand
  166.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  167.  */
  168. openline(f, n)
  169. {
  170.         register int    i;
  171.         register int    s;
  172.  
  173.         if (n < 0)
  174.                 return (FALSE);
  175.         if (n == 0)
  176.                 return (TRUE);
  177.         i = n;                                  /* Insert newlines.     */
  178.         do {
  179.                 s = lnewline();
  180.         } while (s==TRUE && --i);
  181.         if (s == TRUE)                          /* Then back up overtop */
  182.                 s = backchar(f, n);             /* of them all.         */
  183.         return (s);
  184. }
  185.  
  186. /*
  187.  * Insert a newline. Bound to "C-M". If you are at the end of the line and the
  188.  * next line is a blank line, just move into the blank line. This makes "C-O"
  189.  * and "C-X C-O" work nicely, and reduces the ammount of screen update that
  190.  * has to be done. This would not be as critical if screen update were a lot
  191.  * more efficient.
  192.  */
  193. newline(f, n)
  194. {
  195.         int nicol;
  196.         register LINE   *lp;
  197.         register int    s;
  198.  
  199.         if (n < 0)
  200.                 return (FALSE);
  201.         while (n--) {
  202.                 lp = curwp->w_dotp;
  203.                 if (llength(lp) == curwp->w_doto
  204.                 && lp != curbp->b_linep
  205.                 && llength(lforw(lp)) == 0) {
  206.                         if ((s=forwchar(FALSE, 1)) != TRUE)
  207.                                 return (s);
  208.                 } else if ((s=lnewline()) != TRUE)
  209.                         return (s);
  210.         }
  211.         return (TRUE);
  212. }
  213.  
  214. /*
  215.  * Delete blank lines around dot. What this command does depends if dot is
  216.  * sitting on a blank line. If dot is sitting on a blank line, this command
  217.  * deletes all the blank lines above and below the current line. If it is
  218.  * sitting on a non blank line then it deletes all of the blank lines after
  219.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  220.  * ignored.
  221.  */
  222. deblank(f, n)
  223. {
  224.         register LINE   *lp1;
  225.         register LINE   *lp2;
  226.         register int    nld;
  227.  
  228.         lp1 = curwp->w_dotp;
  229.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  230.                 lp1 = lp2;
  231.         lp2 = lp1;
  232.         nld = 0;
  233.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  234.                 ++nld;
  235.         if (nld == 0)
  236.                 return (TRUE);
  237.         curwp->w_dotp = lforw(lp1);
  238.         curwp->w_doto = 0;
  239.         return (ldelete(nld));
  240. }
  241.  
  242. /*
  243.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  244.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  245.  * Figure out the indentation of the current line. Insert a newline by calling
  246.  * the standard routine. Insert the indentation by inserting the right number
  247.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  248.  * subcomands failed. Normally bound to "C-J".
  249.  */
  250. indent(f, n)
  251. {
  252.         register int    nicol;
  253.         register int    c;
  254.         register int    i;
  255.  
  256.         if (n < 0)
  257.                 return (FALSE);
  258.         while (n--) {
  259.                 nicol = 0;
  260.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  261.                         c = lgetc(curwp->w_dotp, i);
  262.                         if (c!=' ' && c!='\t')
  263.                                 break;
  264.                         if (c == '\t')
  265.                                 nicol |= 0x07;
  266.                         ++nicol;
  267.                 }
  268.                 if (lnewline() == FALSE
  269.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  270.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  271.                         return (FALSE);
  272.         }
  273.         return (TRUE);
  274. }
  275.  
  276. /*
  277.  * Delete forward. This is real easy, because the basic delete routine does
  278.  * all of the work. Watches for negative arguments, and does the right thing.
  279.  * If any argument is present, it kills rather than deletes, to prevent loss
  280.  * of text if typed with a big argument. Normally bound to "C-D".
  281.  */
  282. forwdel(f, n)
  283. {
  284.         if (n < 0)
  285.                 return (backdel(f, -n));
  286.         if (f != FALSE) {                       /* Really a kill.       */
  287.                 if ((lastflag&CFKILL) == 0)
  288.                         kdelete();
  289.                 thisflag |= CFKILL;
  290.         }
  291.         return (ldelete(n, f));
  292. }
  293.  
  294. /*
  295.  * Delete backwards. This is quite easy too, because it's all done with other
  296.  * functions. Just move the cursor back, and delete forwards. Like delete
  297.  * forward, this actually does a kill if presented with an argument. Bound to
  298.  * both "RUBOUT" and "C-H".
  299.  */
  300. backdel(f, n)
  301. {
  302.         register int    s;
  303.  
  304.         if (n < 0)
  305.                 return (forwdel(f, -n));
  306.         if (f != FALSE) {                       /* Really a kill.       */
  307.                 if ((lastflag&CFKILL) == 0)
  308.                         kdelete();
  309.                 thisflag |= CFKILL;
  310.         }
  311.         if ((s=backchar(f, n)) == TRUE)
  312.                 s = ldelete(n, f);
  313.         return (s);
  314. }
  315.  
  316. /*
  317.  * Kill text. If called without an argument, it kills from dot to the end of
  318.  * the line, unless it is at the end of the line, when it kills the newline.
  319.  * If called with an argument of 0, it kills from the start of the line to dot.
  320.  * If called with a positive argument, it kills from dot forward over that
  321.  * number of newlines. If called with a negative argument it kills backwards
  322.  * that number of newlines. Normally bound to "C-K".
  323.  */
  324. kill(f, n)
  325. {
  326.         register int    chunk;
  327.         register LINE   *nextp;
  328.  
  329.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  330.                 kdelete();                      /* last wasn't a kill.  */
  331.         thisflag |= CFKILL;
  332.         if (f == FALSE) {
  333.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  334.                 if (chunk == 0)
  335.                         chunk = 1;
  336.         } else if (n == 0) {
  337.                 chunk = curwp->w_doto;
  338.                 curwp->w_doto = 0;
  339.         } else if (n > 0) {
  340.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  341.                 nextp = lforw(curwp->w_dotp);
  342.                 while (--n) {
  343.                         if (nextp == curbp->b_linep)
  344.                                 return (FALSE);
  345.                         chunk += llength(nextp)+1;
  346.                         nextp = lforw(nextp);
  347.                 }
  348.         } else {
  349.                 mlwrite("neg kill");
  350.                 return (FALSE);
  351.         }
  352.         return (ldelete(chunk, TRUE));
  353. }
  354.  
  355. /*
  356.  * Yank text back from the kill buffer. This is really easy. All of the work
  357.  * is done by the standard insert routines. All you do is run the loop, and
  358.  * check for errors. Bound to "C-Y". The blank lines are inserted with a call
  359.  * to "newline" instead of a call to "lnewline" so that the magic stuff that
  360.  * happens when you type a carriage return also happens when a carriage return
  361.  * is yanked back from the kill buffer.
  362.  */
  363. yank(f, n)
  364. {
  365.         register int    c;
  366.         register int    i;
  367.         extern   int    kused;
  368.  
  369.         if (n < 0)
  370.                 return (FALSE);
  371.         while (n--) {
  372.                 i = 0;
  373.                 while ((c=kremove(i)) >= 0) {
  374.                         if (c == '\n') {
  375.                                 if (newline(FALSE, 1) == FALSE)
  376.                                         return (FALSE);
  377.                         } else {
  378.                                 if (linsert(1, c) == FALSE)
  379.                                         return (FALSE);
  380.                         }
  381.                         ++i;
  382.                 }
  383.         }
  384.         return (TRUE);
  385. }
  386.  
  387.